#include "Entity.hpp"
#include "Globals.hpp"
#include <SFML/Graphics/Shape.hpp>
#include <cmath>

Entity::Entity()
	: alive(true),
	distance(0),
	angle(-PI/2),
	width(20),
	height(100),
	creationTime(0),
	debugColor(255, 0, 0, 200)
{
}

void Entity::GetAngleBounds(float& start, float& end)
{
	float x1 = 150 * std::cos(angle) + width / 2 * std::cos(angle - PI/2);
	float y1 = 150 * std::sin(angle) + width / 2 * std::sin(angle - PI/2);
	float x2 = 150 * std::cos(angle) + width / 2 * std::cos(angle + PI/2);
	float y2 = 150 * std::sin(angle) + width / 2 * std::sin(angle + PI/2);
	start = std::atan2f(y1, x1);
	end = std::atan2f(y2, x2);
}

void Entity::Update(float curTime)
{
}

void Entity::Render(sf::RenderTarget* gfx, float x, float y, float worldAngle)
{
	if (g_debugDraw)
	{
		sf::Shape shape = sf::Shape::Line(x, y,
										  x + height * std::cos(angle + worldAngle),
										  y + height * std::sin(angle + worldAngle),
										  width,
										  debugColor);
		float a1, a2;
		GetAngleBounds(a1, a2);
		float cx = g_winWidth / 2;
		float cy = g_winHeight / 2;
		sf::Color lineColor = debugColor;
		lineColor.a = 50;
		sf::Shape line1 = sf::Shape::Line(g_winWidth / 2,
										  g_winHeight / 2,
										  cx + g_winWidth * std::cos(a1 + worldAngle),
										  cy + g_winWidth * std::sin(a1 + worldAngle),
										  2,
										  lineColor);
		sf::Shape line2 = sf::Shape::Line(g_winWidth / 2,
										  g_winHeight / 2,
										  cx + g_winWidth * std::cos(a2 + worldAngle),
										  cy + g_winWidth * std::sin(a2 + worldAngle),
										  2,
										  lineColor);
		gfx->Draw(line1);
		gfx->Draw(line2);
		gfx->Draw(shape);
	}
}

Tree::Tree(float t)
	: preGrowthLevel( MAX_GROWTH_LEVEL )
	, growthLevel( 0 )
{
	creationTime = t;

	image1 = new sf::Image();
	image1->LoadFromFile("resources/tree1.png");
	image2 = new sf::Image();
	image2->LoadFromFile("resources/tree2.png");
	image3 = new sf::Image();
	image3->LoadFromFile("resources/tree3.png");
	image4 = new sf::Image();
	image4->LoadFromFile("resources/tree4.png");
	image5 = new sf::Image();
	image5->LoadFromFile("resources/tree5.png");

	sprite = new sf::Sprite();
	sprite->SetImage(*image1);

	type = ENT_TREE;
}

Tree::~Tree()
{
	delete sprite; sprite = 0;
	delete image5; image5 = 0;
	delete image4; image4 = 0;
	delete image3; image3 = 0;
	delete image2; image2 = 0;
	delete image1; image1 = 0;
}

void Tree::Collide(Entity& rhs, float curTime)
{
	if (rhs.type == ENT_TREE_EATER)
	{
		CollideTreeEaterTree((TreeEater&)rhs, *this, curTime);
	}
}

void Tree::Update(float curTime)
{
	if (!alive)
	{
		if (curTime < killedTime)
			alive = true;
		else
			return;
	}

	float lifeTime = curTime - creationTime;
	width = 10.f + lifeTime / MAX_GROWTH_LEVEL * 50.f;
	height = 50.f + lifeTime / MAX_GROWTH_LEVEL * 75.f;

	/*
	if     ( lifeTime > 5.0f ){ growthLevel = 4; }
	else if( lifeTime > 4.0f ){ growthLevel = 3; }
	else if( lifeTime > 3.0f ){ growthLevel = 2; }
	else if( lifeTime > 2.0f ){ growthLevel = 1; }
	else { growthLevel = 0; }
	*/

	growthLevel = (unsigned int)lifeTime;

	if( growthLevel != preGrowthLevel )
	{
		delete sprite;
		sprite = new sf::Sprite();
		preGrowthLevel = growthLevel;
		if     ( growthLevel == 0 ){ sprite->SetImage(*image1); }
		else if( growthLevel == 1 ){ sprite->SetImage(*image2); }
		else if( growthLevel == 2 ){ sprite->SetImage(*image3); }
		else if( growthLevel == 3 ){ sprite->SetImage(*image4); }
		else if( growthLevel == 4 ){ sprite->SetImage(*image5); }
		else {
			sprite->SetImage(*image5);
			alive = false;
			growthLevel = 0;
		} // for avoid bug
	}
}

void Tree::Render(sf::RenderTarget* gfx, float x, float y, float worldAngle)
{
	//Entity::Render(gfx, x, y, worldAngle);

	

	sprite->SetPosition( x, y );
	sprite->SetCenter( sprite->GetImage()->GetWidth() / 2, sprite->GetImage()->GetHeight());
	sprite->SetRotation( (-angle - worldAngle - PI / 2) * 180 / PI );
	gfx->Draw(*sprite);
}

bool Tree::operator==(const Entity& rhs)
{
	if (rhs.type != type)
		return false;

	const Tree& tree = (const Tree&)rhs;

	return tree.alive == alive &&
		tree.growthLevel == growthLevel;
}

void TreeEater::Collide(Entity& rhs, float curTime)
{
	if (rhs.type == ENT_TREE)
	{
		CollideTreeEaterTree(*this, (Tree&)rhs, curTime);
	}
}

TreeEater::TreeEater()
	: speed(6)
{
	type = ENT_TREE_EATER;
	debugColor = sf::Color(0, 255, 0, 200);
	width = 50;
	height = 20;
}

void TreeEater::Update(float curTime)
{
	float lifeTime = curTime - creationTime;
	
	angle = speed * lifeTime / (2 * PI);
}

void CollideTreeEaterTree(TreeEater& lhs, Tree& rhs, float curTime)
{
	rhs.alive = false;
	rhs.killedTime = curTime;
}